#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include<fstream>
#include<string>
#include<stdlib.h>
#include<cstring>
#include<assert.h>
#include<math.h>

using namespace std;

#define MAX_SIZE 100

class Student
{
public:
    friend void Input(Student stu[]);
    friend void Lookup(Student stu[]);
    friend void Modify(Student stu[]);
    friend void Delete(Student stu[]);
    friend void Output(Student stu[]);
    friend void Pushback(Student stu[]);
    friend void Sort(Student stu[]);
    friend void Write(Student stu[], int n);
    friend int Read(Student stu[]);
    friend int cmp_Student_average(const void* p1, const void* p2);         // use for qsort
private:
    char id[20];
    char name[20];
    char class_0[20];
    float c_program;
    float english;
    float math;
    float average;
}stu[MAX_SIZE];

void Write(Student stu[], int n)
{
    fstream myfile;
    myfile.open("score.txt", ios::out | ios::binary);
    if (!myfile)
    {
        cout << "ERROR! score.txt can't open!" << endl;
        abort();
    }

    int count = n;
    myfile << count << endl << endl;

    for (int i = 0; i < count; i++)
    {
        myfile << stu[i].id << "\t"
            << stu[i].name << "\t"
            << stu[i].class_0 << "\t"
            << stu[i].c_program << "\t"
            << stu[i].english << "\t"
            << stu[i].math << "\t"
            << stu[i].average << endl;
    }

    myfile.close();
}

int Read(Student stu[])
{
    fstream myfile;
    myfile.open("score.txt", ios::in | ios::binary);
    if (!myfile)
    {
        cout << "ERROR! score.txt can't open!" << endl;
        abort();
    }

    int count;
    myfile.seekg(0);
    myfile >> count;

    for (int i = 0; i < count; i++)
    {
        myfile >> stu[i].id >> stu[i].name >> stu[i].class_0
            >> stu[i].c_program >> stu[i].english >> stu[i].math
            >> stu[i].average;
    }

    myfile.close();
    return count;
}

void Input(Student stu[])
{
    system("cls");
    int i = 0;
    int flag;
    char sign = '0';

    cout << endl << "=============== Please input the massage ===============" << endl;
    while (sign != 'n' && sign != 'N')
    {
        assert(i < MAX_SIZE);
        // id
    loop:
        cout << "student ID: ";
        cin >> stu[i].id;

        int c = 0;
        while (c < i)
        {
            c++;
            if (!strcmp(stu[i].id, stu[i - c].id))
            {
                cout << "ERROR! student ID repeat." << endl;
                goto loop;
            }
        }

        // name
        cout << "name: ";
        cin >> stu[i].name;

        // class
        cout << "class: ";
        cin >> stu[i].class_0;

        // score of c_program
        do
        {
            flag = 1;
            cout << "score of c_program: ";
            cin >> stu[i].c_program;
            if (stu[i].c_program > 100 || stu[i].c_program < 0)
                cout << "sorry, please input the number between 0-100!!" << endl;
            else
                flag = 0;
        } while (flag);

        // score of english
        do
        {
            flag = 1;
            cout << "score of english: ";
            cin >> stu[i].english;
            if (stu[i].english > 100 || stu[i].english < 0)
                cout << "sorry, please input the number between 0-100!!" << endl;
            else
                flag = 0;
        } while (flag);

        // score of math
        do
        {
            flag = 1;
            cout << "score of math: ";
            cin >> stu[i].math;
            if (stu[i].math > 100 || stu[i].math < 0)
                cout << "sorry, please input the number between 0-100!!" << endl;
            else
                flag = 0;
        } while (flag);

        // average
        stu[i].average = (stu[i].c_program + stu[i].english + stu[i].math) / 3;
        cout << "the average score is: " << stu[i].average << endl;

        cout << "whether input message?(y or n): ";
        cin >> sign;
        i++;
    }

    Write(stu, i);          // save
}

void Lookup(Student stu[])
{
    system("cls");
    int count = Read(stu);          // number of student
    int i = 0;                      // record subscript
    char id[20];

    cout << "============== Lookup the score of student ==============" << endl;
    cout << "please input the student ID you want to seek: ";
    cin >> id;

    while (strcmp(id, stu[i].id) && i < count)
        i++;

    if (i == count)
        cout << "sorry, student not found." << endl;
    else
    {
        cout << "========================================================" << endl;
        cout << "class: " << stu[i].class_0 << endl;
        cout << "student ID: " << stu[i].id << endl;
        cout << "name: " << stu[i].name << endl;
        cout << "c_program: " << stu[i].c_program << endl;
        cout << "english: " << stu[i].english << endl;
        cout << "math: " << stu[i].math << endl;
        cout << "average: " << stu[i].average << endl;
    }
}

void Modify(Student stu[])
{
    system("cls");
    int count = Read(stu);                  // number of student
    char id[20];
    int i = 0;

    cout << "=============== Modify the grade of students ===============" << endl;
    cout << "input the ID of student who you want to modify: ";
    cin >> id;
    while (strcmp(id, stu[i].id) && i < count)
        i++;

    if (i == count)
    {
        cout << "student not found." << endl;
        return;
    }

    cout << "------------------------------------------------------------" << endl;
    cout << "class" << "\t" << "ID" << "\t" << "name" << "\t"
        << "c_program" << "\t" << "english" << "\t" << "math" << "\t"
        << "average" << endl;
    cout << "------------------------------------------------------------" << endl;
    cout << stu[i].class_0 << "\t" << stu[i].id << "\t" << stu[i].name << "\t"
        << stu[i].c_program << "\t" << stu[i].english << "\t" << stu[i].math << "\t"
        << stu[i].average << endl;

    cout << "please reenter the grade of the student. " << endl;
    cout << "c_program: ";
    cin >> stu[i].c_program;
    cout << "english: ";
    cin >> stu[i].english;
    cout << "math: ";
    cin >> stu[i].math;
    stu[i].average = (stu[i].c_program + stu[i].english + stu[i].math) / 3;
    cout << "average: " << stu[i].average << endl;

    // save
    char sign;
    cout << "whether save the data?(y or n): ";
    cin >> sign;
    if (sign != 'n' && sign != 'N')
        Write(stu, count);
}

void Delete(Student stu[])
{
    system("cls");
    int count = Read(stu);
    int i = 0;
    char id[20];

    cout << "=============== Delete the message of students ===============" << endl;
    cout << "please input the ID of student who you want to delete: ";
    cin >> id;
    while (strcmp(id, stu[i].id) && i < count)
        i++;

    if (i == count)
    {
        cout << "not found." << endl;
        return;
    }

    int j;
    for (j = i; j < count - 1; j++)
    {
        swap(stu[j], stu[j + 1]);
        /*strcpy(stu[j].id, stu[j + 1].id);
        strcpy(stu[j].name, stu[j + 1].name);
        strcpy(stu[j].class_0, stu[j + 1].class_0);

        stu[j].c_program = stu[j + 1].c_program;
        stu[j].english = stu[j + 1].english;
        stu[j].math = stu[j + 1].math;
        stu[j].average = stu[j + 1].average;*/
    }

    // save
    char sign;
    cout << "whether delete?(y or n): ";
    cin >> sign;
    if (sign != 'n' && sign && 'N')
        Write(stu, count - 1);

    cout << "=============== Delete succeed ===============" << endl;
}

void Output(Student stu[])
{
    system("cls");
    int count = Read(stu);

    cout << "=============== Display all students' grade ===============" << endl;
    cout << "-----------------------------------------------------------" << endl;
    cout << "class" << "\t" << "ID" << "\t" << "name" << "\t"
        << "c_program" << "\t" << "english" << "\t" << "math" << "\t"
        << "average" << endl;

    cout << "-----------------------------------------------------------" << endl;
    for (int i = 0; i < count; i++)
    {
        cout << stu[i].class_0 << "\t" << stu[i].id << "\t" << stu[i].name << "\t"
            << stu[i].c_program << "\t" << stu[i].english << "\t" << stu[i].math << "\t"
            << stu[i].average << endl;
    }
}

void Pushback(Student stu[])
{
    system("cls");
    int count = Read(stu);
    char sign = '0';

    cout << "=============== Add student ==============" << endl;
    while (sign != 'n' && sign != 'N')
    {
        assert(count < MAX_SIZE);

        cout << "class: ";
        cin >> stu[count].class_0;
    loop:
        cout << "ID: ";
        cin >> stu[count].id;
        int c = 0;
        while (c < count)
        {
            c++;
            if (!strcmp(stu[count].id, stu[count - c].id))
            {
                cout << "student ID repeat, please try again: " << endl;
                goto loop;
            }
        }

        cout << "name: ";
        cin >> stu[count].name;
        cout << "c_program: ";
        cin >> stu[count].c_program;
        cout << "english: ";
        cin >> stu[count].english;
        cout << "math: ";
        cin >> stu[count].math;

        stu[count].average = (stu[count].english + stu[count].c_program + stu[count].math) / 3;
        count++;

        cout << "whether continue adding?(y or n): " << endl;
        cin >> sign;
    }

    // save
    Write(stu, count);
}

int cmp_Student_average(const void* p1, const void* p2)
{
    return int(((class Student*)p2)->average * pow(10, 4)) - int(((class Student*)p1)->average * pow(10, 4));
}

void Sort(Student stu[])
{
    system("cls");
    int count = Read(stu);
    qsort(stu, count, sizeof(stu[0]), cmp_Student_average);

    // save
    Write(stu, count);
}


int menu()
{
    int c = 0;
    do
    {
        system("cls");
        if (c < 0 || c > 7)
            cout << "ERROR! Please choose again." << endl;

        cout << "=========================================================================" << endl;
        cout << "=============== Welcome to student grade managing system! ===============" << endl;
        cout << "*                      1. input grade                                   *" << endl;
        cout << "*                      2. grade query                                   *" << endl;
        cout << "*                      3. modify grade                                  *" << endl;
        cout << "*                      4. delete student                                *" << endl;
        cout << "*                      5. add student                                   *" << endl;
        cout << "*                      6. rank by average                               *" << endl;
        cout << "*                      7. display all student                           *" << endl;
        cout << "*                      0. exit                                          *" << endl;
        cout << "=========================================================================" << endl;
        cout << " Please choose your operation.(0 - 7) : " << endl;
        cin >> c;
    } while (c < 0 || c > 7);

    // while ((getchar()) != '\n' && (getchar())!= EOF) {}; // clear the buffer

    return (c);
}


int main()
{
    for (;;)
    {
        switch (menu())
        {
        case 1:
            Input(stu);
            break;
        case 2:
            Lookup(stu);
            system("pause");
            break;
        case 3:
            Modify(stu);
            system("pause");
            break;
        case 4:
            Delete(stu);
            system("pause");
            break;
        case 5:
            Pushback(stu);
            system("pause");
            break;
        case 6:
            Sort(stu);
            system("pause");
            break;
        case 7:
            Output(stu);
            system("pause");
            break;
        case 0:
            cout << endl << "===============Thank you for using!===============" << endl;
            exit(0);
        }
    }

    return 0;
}